/**
 * 工具函数模块
 * 提供各种辅助功能
 */

export * from './logger';

/**
 * 解析模板字符串
 * 支持{{expression}}格式的表达式
 * 
 * @param template 模板字符串
 * @param context 上下文对象
 * @returns 解析后的字符串
 */
export function parseTemplate(template: string, context: Record<string, any> = {}): string {
  return template.replace(/{{\s*([^}]+)\s*}}/g, (_, expr) => {
    try {
      // 添加内置函数
      const sandbox = {
        ...context,
        // 生成随机邮箱
        generateEmail: () => `test${Math.floor(Math.random() * 10000)}@example.com`,
        // 生成随机字符串
        randomString: (length = 8) => Math.random().toString(36).substring(2, 2 + length),
        // 当前时间戳
        timestamp: () => Date.now(),
        // 当前日期，格式：YYYY-MM-DD
        currentDate: () => new Date().toISOString().split('T')[0],
        // 数组求和
        sum: (arr: number[]) => arr.reduce((a, b) => a + b, 0)
      };
      
      // 安全地执行表达式
      const result = new Function(...Object.keys(sandbox), `return ${expr};`)(...Object.values(sandbox));
      return result !== undefined ? String(result) : '';
    } catch (error) {
      console.error(`Error parsing template expression: ${expr}`, error);
      return `{{ERROR: ${expr}}}`;
    }
  });
}

/**
 * 等待指定时间
 * @param ms 等待毫秒数
 * @returns Promise
 */
export function sleep(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}

/**
 * 重试函数
 * @param fn 要重试的异步函数
 * @param options 重试选项
 * @returns 函数执行结果的Promise
 */
export async function retry<T>(
  fn: () => Promise<T>, 
  { 
    attempts = 3, 
    delay = 1000, 
    backoff = 2,
    onRetry = (attempt: number, error: Error) => {}
  }: {
    attempts?: number;
    delay?: number;
    backoff?: number;
    onRetry?: (attempt: number, error: Error) => void;
  } = {}
): Promise<T> {
  let lastError: Error;
  
  for (let attempt = 1; attempt <= attempts; attempt++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error as Error;
      
      if (attempt < attempts) {
        onRetry(attempt, lastError);
        const waitTime = delay * Math.pow(backoff, attempt - 1);
        await sleep(waitTime);
      }
    }
  }
  
  throw lastError!;
}